﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TransparentAccords
{
    public partial class FormMainExt : Form
    {
        FormMain frmMain;

        bool bRus { get { return ddlType.SelectedIndex == 0; } }

        public FormMainExt(FormMain frmMain)
        {
            InitializeComponent();
            this.frmMain = frmMain;
            ddlType.SelectedIndex = 0;
        }

        private void FormMainExt_FormClosed(object sender, FormClosedEventArgs e)
        {
            frmMain.Close();
        }

        private void tBtnShortVer_Click(object sender, EventArgs e)
        {
            frmMain.Location = Location;
            frmMain.Show();
            Hide();
        }

        private void FormMainExt_Shown(object sender, EventArgs e)
        {

        }

        class NoteInText
        { 
            public int startInd;
            public int len;
            public Note nt;
            public NoteInText(int startInd, int len, Note nt)
            {
                this.startInd = startInd;
                this.len = len;
                this.nt = nt;
            }
        }

        List<NoteInText> ntL = new List<NoteInText>();

        List<NoteInText> GetNoteList(string Txt)
        {
            List<NoteInText> ntL = new List<NoteInText>();

            // пробегаемся по всем лексемам и ищем аккорды
            bool bSpace = true;
            int SpaceInd = -1;
            for (int i = 0; i <= Txt.Length; i++)
            {
                string lex = "";
                string tmpStr = Txt.Substring(i, Txt.Length - i);
                bool bPar = tmpStr.IndexOf("\\par") == 0 || tmpStr.IndexOf("\\tab")==0;

                if (i == Txt.Length)
                {
                    if ((SpaceInd + 1) < Txt.Length)
                        lex = Txt.Substring(SpaceInd + 1, Txt.Length - SpaceInd - 1);
                }
                else if (Txt[i] == ' ' || bPar)
                {
                    if ((SpaceInd + 1) < Txt.Length) lex = Txt.Substring(SpaceInd + 1, i - SpaceInd - 1);
                    SpaceInd = i;
                    if (bPar) { SpaceInd += 3; i += 3; };
                }

                // если найдена лексема
                if (lex != "")
                {
                    Note nt = StringToNotes(lex);
                    if (nt != null)
                    {
                        int startInd = SpaceInd - lex.Length;
                        if (bPar) startInd -= 3;
                        if (i < Txt.Length) ntL.Add(new NoteInText(startInd, lex.Length, nt));
                        else ntL.Add(new NoteInText(SpaceInd+1, lex.Length, nt));
                    }
                }
            }

            return ntL;
        }

        void Transparent(List<NoteInText> ntL, string Txt)
        {
            TranparentAccords(ntL);
            StringBuilder sb = new StringBuilder();
            RtfStartString(sb);
            int ind = 0;
            for (int i = 0; i < ntL.Count; i++)
            {
                if (ntL[i].startInd != 0) 
                    AddRtfString(sb, Txt.Substring(ind, ntL[i].startInd - ind));
                AddRtfAccord(sb, ntL[i].nt);
                ind = ntL[i].startInd + ntL[i].len;
            }
            if (ind < Txt.Length) AddRtfString(sb, Txt.Substring(ind, Txt.Length - ind));
            sb.AppendLine("}");

            txbRes.Rtf = sb.ToString();
        }

        // поддерживается # b m 5 7 9. Максимальный аккорд G#m7
        Note StringToNotes(string str)
        {
            Note nt = null;
            string s = str.Trim();
            if (s == "") return null;
            if (s.Length > 4) { return null; }
            else
            {
                int n = -1;
                // смотрим ноту
                switch (s[0])
                {
                    case 'C': n = 0; break;
                    case 'D': n = 2; break;
                    case 'E': n = 4; break;
                    case 'F': n = 5; break;
                    case 'G': n = 7; break;
                    case 'A': n = 9; break;
                    case 'B': if (bRus) n = 10; else n = 11; break;
                    case 'H': if (bRus) n = 11; break;
                }
                if (n == -1) return null;

                // ищем диез или бемоль
                bool bFind = false;
                for (int j = 1; j < s.Length; j++)
                {
                    if (s[j] == '#')
                    {
                        if (bFind) return null;
                        // если нота С или B-рус или H
                        if (n == 4 || n == 10 || n == 11) return null;

                        bFind = true;
                        n++;
                    }

                    if (s[j] == 'b')
                    {
                        if (bFind) return null;
                        // если нота С или B-рус или F
                        if (n == 0 || n == 5 || n == 10) return null;
                        bFind = true;
                        n--;
                    }
                }
                nt = new Note(n);

                // ищем минор
                bFind = false;
                for (int j = 1; j < s.Length; j++)
                    if (s[j] == 'm')
                    {
                        if (bFind) return null;
                        bFind = true;
                        nt.Minor = true;
                    }

                // ищем номер
                bFind = false;
                for (int j = 1; j < s.Length; j++)
                {
                    int nm = 0;
                    if (int.TryParse(s[j].ToString(), out nm))
                    {
                        if (bFind) return null;
                        bFind = true;
                        nt.Nm = nm;
                    }
                }

                string ss = s.Substring(1, s.Length - 1).Replace("#", "").Replace("b", "").Replace("m", "").Replace("5", "");
                if (nt.Nm != 5) ss = ss.Replace(nt.Nm.ToString(), "");
                if (ss != "") return null;


            }

            return nt;
        }


        void RtfStartString(StringBuilder sb)
        {
            sb.AppendLine(@"{\rtf1\ansi\ansicpg1251\deff0\deflang1049\deflangfe1049");
            sb.AppendLine("");
            // таблица шрифтов
            /*sb.AppendLine(@"{\fonttbl");
            sb.AppendLine(@"   {\f0\fnil\fcharset0 Arial CYR;}");
            sb.AppendLine(@"   {\f1\fnil\fcharset0 Calibri;}");
            sb.AppendLine("}");
            sb.AppendLine("");*/

            // таблица цветов
            sb.AppendLine(@"{\colortbl");
            sb.AppendLine(@"   {\red255\green255\blue0;}");
            sb.AppendLine(@"   {\red0\green0\blue255;}");
            sb.AppendLine("}");
            sb.AppendLine("");
        }

        void AddRtfString(StringBuilder sb, string str)
        {
            if (sb.Length != 0) sb.Append("\r\n");
            sb.Append(@"{");
            //sb.Append(@"\fs28");
            //sb.Append(@"\f0");
            sb.Append("\r\n" + str);
            sb.Append("\r\n}");
        }

        void AddRtfAccord(StringBuilder sb, Note nt)
        {
            if (sb.Length != 0) sb.Append("\r\n");
            sb.Append(@"{");
            //sb.Append(@"\fs28");
            //sb.Append(@"\f0");
            sb.Append(@"\highlight1");
            sb.Append("\r\n" + nt.ToString());
            sb.Append("\r\n}");
        }

        private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void trTone_Scroll(object sender, EventArgs e)
        {
            lblTone.Text = (trTone.Value - 11).ToString();
            txbRes.Text = "";
            string txt = txbAcc.Text.Replace("\\", "\\\\").Replace("\r\n", "\\par ").Replace("{", "\\{").Replace("}", "\\}").Replace("\t", "\\tab");
            Transparent(GetNoteList(txt), txt);
        }

        void TranparentAccords(List<NoteInText> ntL)
        {
            txbRes.Text = "";
            txbAcc.BackColor = Color.White;
            try
            {
                int sh = Convert.ToInt32(lblTone.Text);
                for (int i = 0; i < ntL.Count; i++)
                {
                    ntL[i].nt.Acc += sh;
                    if (ntL[i].nt.Acc < 0) ntL[i].nt.Acc += 12; if (ntL[i].nt.Acc > 11) ntL[i].nt.Acc -= 12;
                }
            }
            catch (Exception ex) { MessageBox.Show("Ошибка транспонирования: " + ex.Message); }
        }

        private void tBtnMinVer_Click(object sender, EventArgs e)
        {
            frmMain.Location = Location;
            frmMain.Show();
            Hide();
        }
    }
}
